home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.000 / crossfir / crossfire-0.92.4.client / init.c < prev    next >
C/C++ Source or Header  |  1996-04-21  |  11KB  |  421 lines

  1.  
  2. /* This handles the initialization of the client.  This includes making
  3.  * the I_IMAGE and I_ARCH commands.
  4.  */
  5.  
  6. #include <client.h>
  7.  
  8.  
  9. /*
  10.  * A replacement of strdup(), since it's not defined at some
  11.  * unix variants.
  12.  */
  13.  
  14. char *strdup_local(char *str) {
  15.   char *c=(char *)malloc(sizeof(char)*strlen(str)+1);
  16.   strcpy(c,str);
  17.   return c;
  18. }
  19.  
  20.  
  21. void VersionCmd(ArgList msg)
  22. {
  23.   if (ECLIENT_VERSION != ArgList_getLong(msg,2)) {
  24.     printf("Client, Server have different versions (%d,%ld)\n",
  25.        ECLIENT_VERSION,ArgList_getLong(msg,2));
  26.     exit(1);
  27.   }
  28. }
  29.  
  30. void SendVersion(TcpSocket conn)
  31. {
  32.   ArgList msg;
  33.  
  34.   msg = ArgList_create();
  35.   ArgList_addLong(msg,STRINGCOMMAND);
  36.   ArgList_addString(msg,"version");
  37.   ArgList_addLong(msg,ECLIENT_VERSION);
  38.   ArgList_send(conn,msg);
  39.   ArgList_destroy(msg);
  40. }
  41.  
  42.  
  43. void SendAddMe(TcpSocket conn)
  44. {
  45.   ArgList msg;
  46.  
  47.   msg = ArgList_create();
  48.   ArgList_addLong(msg,STRINGCOMMAND);
  49.   ArgList_addString(msg,"addme");
  50.   ArgList_send(conn,msg);
  51.   ArgList_destroy(msg);
  52. }
  53.  
  54.  
  55. void SendSetFaceMode(TcpSocket conn,int mode)
  56. {
  57.   ArgList msg;
  58.  
  59.   msg = ArgList_create();
  60.   ArgList_addLong(msg,STRINGCOMMAND);
  61.   ArgList_addString(msg,"setfacemode");
  62.   ArgList_addChar(msg,mode);
  63.   ArgList_send(conn,msg);
  64.   ArgList_destroy(msg);
  65. }
  66.  
  67.  
  68. #if 0
  69. /* Some config options */
  70. #define MAX_MISSING_FACES 500
  71. #define MAX_MISSING_ARCHS 500
  72.  
  73. static char missing_archs[MAX_MISSING_ARCHS][40];
  74. static int num_missing_archs=0, on_arch_num=0;
  75.  
  76.  
  77. /* This loads up the archetypes that the client uses.  We use to
  78.  * libcross (../common) routines for most of this.
  79.  *
  80.  * This is a lot like the load_archetypes routine in the arch.c file.  The
  81.  * main difference is that we only do one pass - treasures and other
  82.  * arch links we don't care about.
  83.  */
  84.  
  85. void init_client_archetypes()
  86. {
  87.     extern int arch_init;
  88.     int comp;
  89.     char buf[MAX_BUF];
  90.     FILE *fp;
  91.  
  92.     arch_init=1;
  93.     clear_archetable();
  94.     sprintf(buf,"%s/%s", LibDir, ArcheTypes);
  95.     if((fp=open_and_uncompress(buf,0,&comp))==NULL) {
  96.     LOG(llevError,"Can't open archetype file.\n");
  97.     }
  98.     else {
  99.     first_arch_pass(fp);
  100.     close_and_delete(fp, comp);
  101.     }
  102.  
  103.     /* If we have a local file, load that now */
  104.     if (client_libdir && client_archfile) {
  105.     archetype *at = first_archetype, *tmp_arch;
  106.     sprintf(buf,"%s/%s", client_libdir, client_archfile);
  107.     if((fp=open_and_uncompress(buf,0,&comp))==NULL) {
  108.         LOG(llevError,"Can't open archetype file.\n");
  109.     }
  110.     else {
  111.         first_arch_pass(fp);
  112.         close_and_delete(fp, comp);
  113.         /* the first_arch_passes sets the first_archetype pointer.
  114.          * We preserved the previous value, now we need to
  115.          * connect the two lists.  If at is null, it means that
  116.          * there was not a previous first pass - thus, we only
  117.          * need to do things when it is not null.
  118.          */
  119.         if (at!=NULL) {
  120.         tmp_arch = first_archetype;
  121.         /* Go to the end of the archetypes we just loaded.
  122.          * This should be a shorter list than the standard
  123.          * file
  124.          */
  125.         while (tmp_arch->next)
  126.             tmp_arch=tmp_arch->next;
  127.             /* tmp_arch->next is now null.  So connect the list */
  128.         tmp_arch->next = at;
  129.         }
  130.     }
  131.     }
  132.     init_archetable();
  133.     arch_init=0;
  134. }
  135.  
  136. int request_missing_archs(int max_requests)
  137. {
  138.  
  139.     while (on_arch_num<num_missing_archs && pending_archs<max_requests) {
  140.     write_socket("REQUEST %s ARCH\n", missing_archs[on_arch_num]);
  141.         pending_archs++;
  142.         on_arch_num++;
  143.     }
  144.     if (pending_archs || on_arch_num<num_missing_archs) return 1;
  145.     return 0;
  146. }
  147. void add_missing_arch_name(char *buf)
  148. {
  149.     strcpy(missing_archs[num_missing_archs++],buf);
  150. }
  151.  
  152. /* This gets all the image names from the server.  It then
  153.  * compares it against the list it read in.  Any archetypes the
  154.  * server has but the client does not are then requested.
  155.  */
  156. void get_arch_names(char *buf)
  157. {
  158.     char *cp;
  159.  
  160.     do {
  161.     if ((cp = strchr(buf,' '))!=NULL) *cp++='\0';
  162.  
  163.     if (!strcmp(buf,"START")) {
  164.         num_missing_archs=0;
  165.         on_arch_num=0;
  166.     }
  167.     else if (!strcmp(buf,"END")) {
  168.         int i;
  169.  
  170.         for (i=0; i<num_missing_archs; i++)
  171.         printf("missing arch %s\n", missing_archs[i]);
  172.     }
  173.     else {
  174.         if (find_archetype(buf)==NULL) {
  175.         add_missing_arch_name(buf);
  176.         if (num_missing_archs==MAX_MISSING_ARCHS) {
  177.             fprintf(stderr,"Error - too many missing archetypes.\n");
  178.             exit(1);
  179.         }
  180.         }
  181.     }
  182.     buf = cp;
  183.     } while (buf!=NULL);
  184. }
  185.  
  186.  
  187. static char missing_faces[MAX_MISSING_FACES][30];
  188. static int num_missing_faces=0, on_face_num=0;
  189.  
  190. /* This function goes through the missing_faces array and requests
  191.  * that the images be sent.  It only does a few at a time, so that
  192.  * it won't get swamped
  193.  * returns TRUE if there is more images to be requested or
  194.  * received (pending requests), FALSE if all the images have been requested
  195.  * and received.  The reason that pending images is checked is so that
  196.  * the client does not request more data to be transmitted, thus
  197.  * overflowing the server buffers (which will then cause the connection
  198.  * to close)
  199.  *
  200.  */
  201. int request_missing_images(int max_requests)
  202. {
  203.  
  204.     while (on_face_num<num_missing_faces && pending_images<max_requests) {
  205.     write_socket("REQUEST %s %s\n", missing_faces[on_face_num],
  206.         (display_mode==Xpm_Display)?"XPM":"BIT");
  207.         pending_images++;
  208.         on_face_num++;
  209.     }
  210.     if (pending_images || on_face_num<num_missing_faces) return 1;
  211.     return 0;
  212. }
  213.  
  214. /* This adds an image name to the array of missing images (above).
  215.  * Right now, this is only called from load_additional_images when
  216.  * we do not find an image.  load_additional_images is called 
  217.  * before we request all the image names.  Thus, request_missing_images
  218.  * is called before we send the SEND_IMAGE_NAMES request to the 
  219.  * server.
  220.  */
  221. void add_missing_image_name(char *buf)
  222. {
  223.     strcpy(missing_faces[num_missing_faces++],buf);
  224. }
  225.  
  226. /* This gets all the image names from the server.  It then
  227.  * compares it against the list it read in.  Any images the
  228.  * server has but the client does not are then requested.
  229.  */
  230. void get_image_names(char *buf)
  231. {
  232.     char *cp;
  233.  
  234.     do {
  235.     if ((cp = strchr(buf,' '))!=NULL) *cp++='\0';
  236.  
  237.     if (!strcmp(buf,"START")) {
  238.         num_missing_faces=0;
  239.         on_face_num=0;
  240.     }
  241.     else if (!strcmp(buf,"END")) {
  242.         int i;
  243.  
  244.         for (i=0; i<num_missing_faces; i++)
  245.         printf("missing face %s\n", missing_faces[i]);
  246.     }
  247.     else {
  248.         if (FindFace(buf,-1)==-1) {
  249.         strcpy(missing_faces[num_missing_faces++],buf);
  250.         if (num_missing_faces==MAX_MISSING_FACES) {
  251.             fprintf(stderr,"Error - too many missing faces.\n");
  252.             exit(1);
  253.         }
  254.         }
  255.     }
  256.     buf = cp;
  257.     } while (buf!=NULL);
  258. }
  259.  
  260.  
  261. /* This functions makes the preliminary/startup requests to the
  262.  * server.
  263.  */
  264.  
  265. void init_client_requests()
  266. {
  267.  
  268.     int  timeout=5000000,got_input;
  269.  
  270.     /* Init states.  Using an enumeration has the advantage that
  271.      * a new state can be added between other states with very little
  272.      * difficulty.  _R_ stands for _Request_ - just an abbreviation
  273.      * to make things easier.
  274.      */
  275.     enum {Request_Image1, Request_Image_Names,
  276.     Request_Image2, Request_Arch_Names, Request_Archs, Finished}
  277.     init_state=Request_Image1;
  278.  
  279.     while (init_state!=Finished) {
  280.     got_input=command_loop(timeout);
  281.  
  282.     /* init_state is what stage of initialization we are on.
  283.      * during this phase, we have very long timeouts (5 seconds,
  284.      * but this is an arbitrary number).  If we haven't gotten
  285.      * any data in that time, we go to the next state.
  286.      * Unfortunately, this makes for a bit longer startup time.
  287.      *
  288.      * note that the init states are meant to break through -
  289.      * thus it could go from state 1 to 5 without ever doing
  290.      * a read if none of those states does anything (due
  291.      * to command line options or other reasons
  292.      * Thus, all init_state checks should be in order that they
  293.      * are defined in the enumeration type.
  294.      */
  295.  
  296.     /* First image request stage - this requests images that were
  297.      * missing during the load_additional_image function call.
  298.      * Only give so much time for the server to send us the
  299.      * imagess - otherwise, we would never leave the loop.
  300.      * (perhaps not make the error fatal?)
  301.      */
  302.     if (init_state==Request_Image1) {
  303.         static int retries=0;
  304.  
  305.         if (request_missing_images(5)) {
  306.         if (!got_input) {
  307.             if (++retries>MAX_RETRIES) {
  308.             LOG(llevError,"Exceeded retries on requesting images.\n");
  309.             exit(1);
  310.             }
  311.         }
  312.         else retries=0;
  313.         continue;
  314.         }
  315.         else init_state++;
  316.     }
  317.     /* Request the image names.  Only make the request if the
  318.      * player has invoked us with the right options (init_load_image
  319.      * is true.)  In either case, go to the next state
  320.      */
  321.     if (init_state==Request_Image_Names) {
  322.         init_state++;
  323.         if (init_load_image) {
  324.         write_socket("SEND_IMAGE_NAMES\n");
  325.         continue;    /* So that we will read in the response */
  326.         }
  327.     }
  328.     /* Request missing images that we found about about
  329.      * from the SEND_IMAGE_NAMES request (above).  There will be
  330.      * no images to request in this stage if we did not
  331.      * send a SEND_IMAGE_NAME request.
  332.      * Otherwise, this code is the same as that in the Request_Image1
  333.      * stage.
  334.      */
  335.     if (init_state==Request_Image2) {
  336.         static int retries=0;
  337.  
  338.         if (request_missing_images(5)) {
  339.         if (!got_input) {
  340.             if (++retries>MAX_RETRIES) {
  341.             LOG(llevError,"Exceeded retries on requesting images.\n");
  342.             exit(1);
  343.             }
  344.         }
  345.         else retries=0;
  346.         continue;
  347.         }
  348.         else init_state++;
  349.     }
  350.  
  351.     /* This is like the request for image names, but
  352.      * is the archetype names instead.
  353.      */
  354.     if (init_state==Request_Arch_Names) {
  355.         init_state++;
  356.         if (init_load_arch) {
  357.         write_socket("SEND_IMAGE_ARCH\n");
  358.         continue;    /* So that we will read in the response */
  359.         }
  360.     }
  361.     /* Now we go through and request the archetyps we are missing.
  362.      * Same thing as the requesting the images above.
  363.      */
  364.     if (init_state==Request_Archs) {
  365.         static int retries=0;
  366.  
  367.         if (request_missing_archs(5)) {
  368.         if (!got_input) {
  369.             if (++retries>MAX_RETRIES) {
  370.             LOG(llevError,"Exceeded retries on requesting images.\n");
  371.             exit(1);
  372.             }
  373.         }
  374.         else retries=0;
  375.         continue;
  376.         }
  377.         else init_state++;
  378.     }
  379.     }
  380. }
  381.  
  382. #endif
  383. void init_client_vars()
  384. {
  385.     int i;
  386.  
  387.  
  388.     client_libdir=getenv("CFCLIENT_LIBDIR");
  389. #ifdef CLIENT_LIBDIR
  390.     if (client_libdir==NULL)
  391.     client_libdir=CLIENT_LIBDIR;
  392. #endif
  393.     client_archfile = getenv("CFCLIENT_ARCHFILE");
  394. #ifdef CLIENT_ARCHFILE
  395.     if (client_archfile==NULL)
  396.     client_archfile=CLIENT_ARCHFILE;
  397. #endif
  398.  
  399.     cpl.count_left = 0;
  400.     cpl.container = NULL;
  401.     cpl.show_what = 0;
  402.     memset(&cpl.stats,0, sizeof(Stats));
  403.     cpl.stats.maxsp=1;    /* avoid div by 0 errors */
  404.     cpl.stats.maxhp=1;    /* ditto */
  405.     cpl.stats.maxgrace=1;    /* ditto */
  406.     /* ditto - displayed weapon speed is weapon speed/speed */
  407.     cpl.stats.speed=1;
  408.     cpl.input_text[0]='\0';
  409.     cpl.title[0] = '\0';
  410.     cpl.range[0] = '\0';
  411.  
  412.     for (i=0; i<range_size; i++)
  413.     cpl.ranges[i]=NULL;
  414.  
  415.     cpl.map_x=0;
  416.     cpl.map_y=0;
  417.  
  418.     cpl.ob = player_item();
  419.     cpl.below = map_item();
  420. }
  421.